using System;
using System.Collections.Generic;
using FireStarter.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.Base.Exceptions;
using Habanero.BO;
using Habanero.Testability;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    /// <summary>
    /// Provides a place to write custom tests for DMUniqueConstraint objects.
    /// This file is only written once and can be changed.  The Def file
    /// attached to this as a dependent is rewritten with each regeneration
    /// and contains the standard tests for DMUniqueConstraint.
    /// Regenerate this test project whenever there have been changes to the
    /// business objects.
    /// If tests are failing due to a unique setup in your application,
    /// you can either override the Create methods in TestUtils, or you
    /// can add the test to the ignore list below and reimplement it here.
    /// </summary>
    public partial class TestDMUniqueConstraint
    {
        [SetUp]
        public override void SetupTest()
        {
            //Runs every time that any testmethod is executed
            base.SetupTest();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //------------------------------------------------------------
            // Use this list to ignore generated tests that are failing
            // due to a unique condition in your application.
            // Remember to reimplement the test here.
            //------------------------------------------------------------
            //_ignoreList.Add("TestMethodName", "Reason for ignoring it");
            base.SetupFixture();
            GlobalRegistry.UIExceptionNotifier = new RethrowingExceptionNotifier();
        }

        [TearDown]
        public override void TearDownTest()
        {
            //runs every time any testmethod is complete
            base.TearDownTest();
        }

        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsDMUniqueConstraint.CreateUnsavedValidDMUniqueConstraint();
            //---------------Assert Precondition----------------
            Assert.IsFalse(String.IsNullOrEmpty(dmUniqueConstraint.UniqueConstraintName), "UniqueConstraintName Should not be null");
            //---------------Execute Test ----------------------
            string actualToString = dmUniqueConstraint.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmUniqueConstraint.UniqueConstraintName, actualToString);
        }

        [Test]
        public void Test_ToString_UniqueConstraintNameNull()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsDMUniqueConstraint.CreateUnsavedValidDMUniqueConstraint();
            dmUniqueConstraint.UniqueConstraintName = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dmUniqueConstraint.UniqueConstraintName), "UniqueConstraintName Should be null");
            //---------------Execute Test ----------------------
            string actualToString = dmUniqueConstraint.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmUniqueConstraint.UniqueConstraintID.ToString(), actualToString);
        }

        [Test]
        public void Test_ToString_UniqueConstraintNameNull_UniqueConstraintIDNull()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsDMUniqueConstraint.CreateUnsavedValidDMUniqueConstraint();
            dmUniqueConstraint.UniqueConstraintName = null;
            dmUniqueConstraint.UniqueConstraintID = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dmUniqueConstraint.UniqueConstraintName), "UniqueConstraintName Should be null");
            Assert.IsNull(dmUniqueConstraint.UniqueConstraintID);
            //---------------Execute Test ----------------------
            string actualToString = dmUniqueConstraint.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual("-unnamed UniqueConstraint-", actualToString);
        }

        [Test]
        public void Test_InsertNewUniqueConstraintInfo()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsShared.CreateUnsavedValidUniqueConstraintInfo();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmUniqueConstraint.Status.IsNew);

            //---------------Execute Test ----------------------
            dmUniqueConstraint.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmUniqueConstraint.Status.IsNew);
        }

        [Test]
        public void Test_InsertNewUniqueConstraintInfo_Invalid()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = new DMUniqueConstraint();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmUniqueConstraint.Status.IsNew);

            //---------------Execute Test ----------------------
            try
            {
                dmUniqueConstraint.Save();
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                StringAssert.Contains("Class ID' is a compulsory field and has no value", ex.Message);
                StringAssert.Contains("Unique Constraint Name' is a compulsory field and has no value", ex.Message);
            }
            Assert.IsTrue(dmUniqueConstraint.Status.IsNew);
        }

        [Test]
        public void Test_DeleteUniqueConstraintInfo()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsShared.CreateSavedUniqueConstraintInfo();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmUniqueConstraint.Status.IsNew);
            string message;
            Assert.IsTrue(dmUniqueConstraint.IsDeletable(out message));

            //---------------Execute Test ----------------------
            dmUniqueConstraint.MarkForDelete();
            dmUniqueConstraint.Save();

            //---------------Test Result -----------------------  
            Assert.IsTrue(dmUniqueConstraint.Status.IsNew);
            Assert.IsTrue(dmUniqueConstraint.Status.IsDeleted);
        }

        [Test]
        public void Test_UpdateUniqueConstraintInfo()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsShared.CreateSavedUniqueConstraintInfo();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmUniqueConstraint.Status.IsNew);
            string message;
            Assert.IsTrue(dmUniqueConstraint.IsEditable(out message));

            //---------------Execute Test ----------------------
            dmUniqueConstraint.IgnoreIfNull = false;
            dmUniqueConstraint.Generated = true;
            dmUniqueConstraint.Message = TestUtilsShared.GetRandomString();
            dmUniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();

            dmUniqueConstraint.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmUniqueConstraint.Status.IsNew);
        }

        [Test]
        public void Test_LoadUniqueConstraintInfo()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint dmUniqueConstraint = TestUtilsShared.CreateSavedUniqueConstraintInfo();
            BusinessObjectManager.Instance.ClearLoadedObjects();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DMUniqueConstraint loadedDMUniqueConstraint = Broker.GetBusinessObject<DMUniqueConstraint>
                (dmUniqueConstraint.ID);

            //---------------Test Result -----------------------  
            Assert.IsFalse(loadedDMUniqueConstraint.Status.IsNew);
            Assert.AreEqual(loadedDMUniqueConstraint.ID, dmUniqueConstraint.ID);
            //TODO: When not using memory db Assert.AreNotSame(loadedDMClass, businessObjectInfo);
        }

        [Test]
        public void Test_GetKeyProperties()
        {
            //---------------Set up test pack-------------------

            DMUniqueConstraint dmUniqueConstraint = TestUtilsShared.CreateSavedUniqueConstraintInfo();
            DMUniqueConstraintProperty dmUniqueConstraintProperty = TestUtilsShared.CreateSavedUniqueConstraintPropertyInfo
                (dmUniqueConstraint);
            BusinessObjectManager.Instance.ClearLoadedObjects();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmUniqueConstraint.Status.IsNew);
            Assert.AreEqual(1, dmUniqueConstraint.UniqueConstraintProperties.Count);

            //---------------Execute Test ----------------------
            DMUniqueConstraintProperty loadedDMUniqueConstraintProperty =
                dmUniqueConstraint.UniqueConstraintProperties[0];

            //---------------Test Result -----------------------
            Assert.AreEqual(dmUniqueConstraintProperty.ID, loadedDMUniqueConstraintProperty.ID);
        }

        [Test]
        public void Test_UniqueConstraint_WithSamePropertyAsPrimaryKey_ShouldRaiseError()
        {
            //--------------- Set up test pack ------------------
            DMObjectIdentity dmObjectIdentity = TestUtilsShared.CreateUnsavedValidObjectIdentityInfo();
            DMClass dmClass = dmObjectIdentity.Class;
            DMUniqueConstraint dmUniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            dmUniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(1, dmObjectIdentity.Properties.Count);
            //--------------- Execute Test ----------------------
            DMProperty property = dmObjectIdentity.Properties[0];
            dmUniqueConstraint.AddPropertyInfo(property);
            try
            {
                dmUniqueConstraint.Save();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                StringAssert.Contains("You cannot have a unique constraint for the entity '" + dmClass.ToString() + "' with the same properties as the primary key", ex.Message);
            }
        }

        [Test]
        public void Test_UniqueConstraint_WithDiffPropertiesAsPrimaryKey_ShouldNotRaiseError()
        {
            //--------------- Set up test pack ------------------
            DMObjectIdentity dmObjectIdentity = TestUtilsShared.CreateUnsavedValidObjectIdentityInfo();
            DMClass dmClass = dmObjectIdentity.Class;
            DMProperty property2 = TestUtilsShared.CreateUnsavedValidDMProperty(dmClass);
            DMUniqueConstraint dmUniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            dmUniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(1, dmObjectIdentity.Properties.Count);
            Assert.IsTrue(dmUniqueConstraint.Status.IsNew);
            //--------------- Execute Test ----------------------
            DMProperty property = dmObjectIdentity.Properties[0];
            dmUniqueConstraint.AddPropertyInfo(property);
            dmUniqueConstraint.AddPropertyInfo(property2);
            dmUniqueConstraint.Save();
            //---------------Test Result -----------------------
            Assert.IsFalse(dmUniqueConstraint.Status.IsNew);

        }

        
        [Test]
        public void Test_CannotHaveSamePropTwice()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            uniqueConstraint.AddPropertyInfo(dmProperty);
           
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(1,uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            
            try
            {
                uniqueConstraint.AddPropertyInfo(dmProperty);
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (Exception ex)
            {
                StringAssert.Contains(string.Format("A property with name '{0}' could not be added to the Alternate Key Info " + 
                    "for the business object '{1}' since it already exists in the business object alternate key", 
                    dmProperty.PropertyName, dmClass.ClassNameBO), ex.Message);
            }
            
        }

        [Test]
        public void Test_HasProperty_WhenOnePropMatches_ShouldReturnTrue()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            uniqueConstraint.AddPropertyInfo(dmProperty);
           
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(1, uniqueConstraint.Properties.Count);
            Assert.AreEqual(1, uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            bool hasProperty = uniqueConstraint.HasProperty(dmProperty);
            //--------------- Test Result -----------------------
            Assert.IsTrue(hasProperty);
        }
        [Test]
        public void Test_HasProperty_When_TwoPropsOneMatches_ShouldReturnTrue()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            uniqueConstraint.AddPropertyInfo(dmClass.Properties.CreateBusinessObject());
            uniqueConstraint.AddPropertyInfo(dmProperty);

            //--------------- Test Preconditions ----------------
            Assert.AreEqual(2, uniqueConstraint.Properties.Count);
            Assert.AreEqual(2, uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            bool hasProperty = uniqueConstraint.HasProperty(dmProperty);
            //--------------- Test Result -----------------------
            Assert.IsTrue(hasProperty);
        }
        [Test]
        public void Test_HasProperty_When_TwoProps_NonMatch_ShouldReturnFalse()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            uniqueConstraint.AddPropertyInfo(dmClass.Properties.CreateBusinessObject());
            uniqueConstraint.AddPropertyInfo(dmProperty);

            //--------------- Test Preconditions ----------------
            Assert.AreEqual(2, uniqueConstraint.Properties.Count);
            Assert.AreEqual(2, uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            bool hasProperty = uniqueConstraint.HasProperty(dmClass.Properties.CreateBusinessObject());
            //--------------- Test Result -----------------------
            Assert.IsFalse(hasProperty);
        }
        [Test]
        public void Test_AreAllPropertiesEqual_When_TwoProps_NonMatch_ShouldReturnFalse()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            uniqueConstraint.AddPropertyInfo(dmClass.Properties.CreateBusinessObject());
            uniqueConstraint.AddPropertyInfo(dmProperty);
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(2, uniqueConstraint.Properties.Count);
            Assert.AreEqual(2, uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            IList<DMProperty> properties = new List<DMProperty> { dmProperty};
            bool hasProperties = uniqueConstraint.AreAllPropertiesEqual(properties);
            //--------------- Test Result -----------------------
            Assert.IsFalse(hasProperties);
        }
        [Test]
        public void Test_AreAllPropertiesEqual_When_TwoProps_NoMatch_ShouldReturnFalse()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            uniqueConstraint.AddPropertyInfo(dmClass.Properties.CreateBusinessObject());
            uniqueConstraint.AddPropertyInfo(dmProperty);
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(2, uniqueConstraint.Properties.Count);
            Assert.AreEqual(2, uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            IList<DMProperty> properties = new List<DMProperty> { dmProperty, dmClass.Properties.CreateBusinessObject() };
            bool hasProperties = uniqueConstraint.AreAllPropertiesEqual(properties);
            //--------------- Test Result -----------------------
            Assert.IsFalse(hasProperties);
        }
        [Test]
        public void Test_AreAllPropertiesEqual_When_TwoProps_BothMatch_ShouldReturnTrue()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateSavedDMClassWithProps();
            DMProperty dmProperty = dmClass.Properties[0];
            DMUniqueConstraint uniqueConstraint = dmClass.UniqueConstraints.CreateBusinessObject();
            uniqueConstraint.UniqueConstraintName = TestUtilsShared.GetRandomString();
            DMProperty dmProperty1 = dmClass.Properties.CreateBusinessObject();
            uniqueConstraint.AddPropertyInfo(dmProperty1);
            uniqueConstraint.AddPropertyInfo(dmProperty);
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(2, uniqueConstraint.Properties.Count);
            Assert.AreEqual(2, uniqueConstraint.UniqueConstraintProperties.Count);
            //--------------- Execute Test ----------------------
            IList<DMProperty> properties = new List<DMProperty> { dmProperty, dmProperty1 };
            bool hasProperties = uniqueConstraint.AreAllPropertiesEqual(properties);
            //--------------- Test Result -----------------------
            Assert.IsTrue(hasProperties);
        }
         [Test]
        public void Test_GetParent_Null()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint uniqueConstraint = new DMUniqueConstraint();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IModelElement parent = ((IModelKey) uniqueConstraint).Parent;
            //---------------Test Result -----------------------
            Assert.IsNull(parent);
        }

        [Test]
        public void Test_GetParent()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint uniqueConstraint = new DMUniqueConstraint();
            DMClass dmClass = new DMClass();
            uniqueConstraint.Class = dmClass;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IModelElement parent = ((IModelKey) uniqueConstraint).Parent;
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, parent);
        }

        [Test]
        public void Test_SetParentExceptionThrown()
        {
            //---------------Set up test pack-------------------
            IModelKey modelKey = new DMUniqueConstraint();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            Exception exceptionThrown = null;
            try
            {
                modelKey.Parent = new DMClass();
            }
            catch (Exception ex)
            {
                exceptionThrown = ex;
            }
            //---------------Test Result -----------------------
            Assert.IsNotNull(exceptionThrown);
            Assert.IsInstanceOf(typeof (HabaneroDeveloperException), exceptionThrown);
            StringAssert.Contains
                ("Set the parent of the IModelKey by setting the related Class object", exceptionThrown.Message);
        }

        [Test]
        public void Test_KeyName()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint uniqueConstraint = new DMUniqueConstraint();
            string keyName = RandomValueGen.GetRandomString();
            uniqueConstraint.UniqueConstraintName = keyName;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string testKeyName = ((IModelKey) uniqueConstraint).KeyName;
            //---------------Test Result -----------------------
            Assert.AreEqual(keyName, testKeyName);
        }

        [Test]
        public void Test_KeyProperties()
        {
            //---------------Set up test pack-------------------
            DMUniqueConstraint uniqueConstraint = new DMUniqueConstraint();
            DMProperty dmProperty1 = CreateDMProperty(RandomValueGen.GetRandomString());
            DMProperty dmProperty2 = CreateDMProperty(RandomValueGen.GetRandomString());
            uniqueConstraint.AddPropertyInfo(dmProperty1);
            uniqueConstraint.AddPropertyInfo(dmProperty2);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IList<IModelProperty> keyProperties = ((IModelKey) uniqueConstraint).KeyProperties;
            //---------------Test Result -----------------------
            Assert.AreEqual(2, keyProperties.Count);
            Assert.AreSame(dmProperty1, keyProperties[0]);
            Assert.AreSame(dmProperty2, keyProperties[1]);
        }

        private static DMProperty CreateDMProperty(string propertyName)
        {
            DMProperty dmProperty = new DMProperty();
            dmProperty.PropertyName = propertyName;
            return dmProperty;
        }
       }
    }

